// ***************************************************************************************
// Copyright (c) 2023-2025 Peng Cheng Laboratory
// Copyright (c) 2023-2025 Institute of Computing Technology, Chinese Academy of Sciences
// Copyright (c) 2023-2025 Beijing Institute of Open Source Chip
//
// iEDA is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
//
// See the Mulan PSL v2 for more details.
// ***************************************************************************************
/**
 * @File Name: contest_dm.cpp
 * @Brief :
 * @Author : Yell (12112088@qq.com)
 * @Version : 1.0
 * @Creat Date : 2023-09-15
 *
 */

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "contest_dm.h"

namespace ieda_contest {

ContestDataManager::ContestDataManager(double gcell_x, double gcell_y, std::string guide_input, std::string guide_output)
{
  // _guide_input 和 _guide_output 被初始化为传入的字符串参数
  _guide_input = guide_input;
  _guide_output = guide_output;

  // 输出 "Contest process flow"
  if (std::abs(gcell_x) < 1e-6 && std::abs(gcell_y) < 1e-6 && _guide_input != "") {
    std::cout << " ---------------Contest process flow-----------------" << std::endl;
  } else if (std::abs(gcell_x) > 1e-6 && std::abs(gcell_y) > 1e-6 && _guide_input == "") {
    std::cout << " ---------------Contest Preprocess flow-----------------" << std::endl;
  } else {
    std::cout << " error input" << std::endl;
  }

  // 初始化数据库: 创建 ContestDB 的实例，并设置网格单元的横纵尺寸
  _database = new ContestDB();
  _database->set_single_gcell_x_span(gcell_x);
  _database->set_single_gcell_y_span(gcell_y);

  // 获取布局和设计信息: 从某个全局或外部实例 dmInst 获取 IdbLayout 和 IdbDesign 的信息
  _idb_layout = dmInst->get_idb_builder()->get_lef_service()->get_layout();
  _idb_design = dmInst->get_idb_builder()->get_def_service()->get_design();

  // add more
  _instance_list = dmInst->get_idb_design()->get_instance_list()->get_instance_list();
}

// ContestDataManager 类的析构函数。它的作用是在 ContestDataManager 对象被销毁时释放资源
ContestDataManager::~ContestDataManager()
{
  if (_database != nullptr) {
    delete _database;
    _database = nullptr;
  }
}

bool ContestDataManager::buildData()
{
  // 如果任何一个是 nullptr，方法返回 false，表示数据构建失败
  if (_idb_layout == nullptr || _idb_design == nullptr) {
    return false;
  }

  // 如果 _idb_layout 和 _idb_design 都有效，创建一个 ContestWrapper 实例
  // 传入 _database、_idb_layout 和 _idb_design
  // 然后调用 ContestWrapper 的 transfer_idb_to_contest 方法
  // 并将结果存储在 b_result
  ContestWrapper wrapper(_database, _idb_layout, _idb_design);
  bool b_result = wrapper.transfer_idb_to_contest();

  // 如果 _guide_input 非空，创建 GuideParser 实例，并调用其 parse 方法
  // 传入 _guide_input 和 _database 获取的网列表。使用 &= 更新 b_result 的值
  // 这意味着如果任一步骤失败，b_result 将变为 false
  if (_guide_input != "") {
    /// build data from guide file
    GuideParser parser;
    b_result &= parser.parse(_guide_input, _database->get_net_list());
  }

  return b_result;
}

bool ContestDataManager::saveData()
{
  // 和前面一样
  if (_idb_layout == nullptr || _idb_design == nullptr) {
    return false;
  }
  ContestWrapper wrapper(_database, _idb_layout, _idb_design);
  bool b_result = wrapper.transfer_contest_to_idb();

  /// save data to guide
  GuideParser parser;
  b_result &= parser.save(_guide_output, _database->get_net_list());

  return b_result;
}

}  // namespace ieda_contest
